/* eslint-disable no-nested-ternary */
import { computed, defineComponent, onUnmounted, ref, watch } from 'vue';
import {
  getEditorEmits,
  getInputProps,
  useNamespace,
} from '@ibiz-template/vue3-util';
import { IChatMessage, IPortalAsyncAction } from '@ibiz-template/core';
import { createUUID } from 'qx-util';
import { TextBoxEditorController } from '../text-box-editor.controller';
import './input.scss';

export const IBizInput = defineComponent({
  name: 'IBizInput',
  props: getInputProps<TextBoxEditorController>(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('input');
    const c = props.controller;
    const editorModel = c.model;

    // 是否编辑态
    const isEditable = ref(false);

    // 编辑器Ref
    const editorRef = ref();

    // 是否显示限制长度
    const showLimit = ref(true);

    // 文本域是否自适应高度
    const isAuto = ref(false);

    // 文本域默认行数，仅在 textarea 类型下有效
    const rows = ref(2);
    if (editorModel.editorType === 'TEXTAREA_10') {
      rows.value = 10;
    }

    if (c.editorParams) {
      if (c.editorParams.SHOWLIMIT === 'false') {
        showLimit.value = false;
      }
      if (c.editorParams.ISAUTO === 'true') {
        isAuto.value = true;
      }
    }

    // 类型
    const type = computed(() => {
      switch (editorModel.editorType) {
        case 'TEXTBOX':
          return 'text';
        case 'PASSWORD':
          return 'password';
        case 'TEXTAREA':
        case 'TEXTAREA_10':
          return 'textarea';
        default:
          return 'string';
      }
    });

    // 是否显示表单默认内容
    const showFormDefaultContent = computed(() => {
      if (
        props.controlParams &&
        props.controlParams.editmode === 'hover' &&
        !props.readonly
      ) {
        return true;
      }
      return false;
    });

    const currentVal = ref<string>('');

    watch(
      () => props.value,
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          if (newVal == null) {
            currentVal.value = '';
          } else {
            currentVal.value = newVal.toString();
          }
        }
      },
      { immediate: true },
    );

    const setEditable = (flag: boolean) => {
      if (flag) {
        isEditable.value = flag;
      } else {
        setTimeout(() => {
          isEditable.value = flag;
        }, 100);
      }
    };

    let blurCacheValue: string | undefined;
    // 值变更
    const handleChange = (val: string | number) => {
      // 拦截掉blur触发后change
      if (blurCacheValue !== val) {
        emit('change', val);
      }
      blurCacheValue = undefined;
    };

    const handleKeyUp = (e: KeyboardEvent) => {
      if (e && e.code === 'Enter') {
        emit('enter', e);
        editorRef.value.$el.dispatchEvent(e);
      }
    };

    /**
     * blur时马上抛值变更
     * @author lxm
     * @date 2023-03-06 06:36:23
     */
    const onBlur = (event: IData) => {
      blurCacheValue = event.target.value;
      // eslint-disable-next-line eqeqeq
      if (blurCacheValue != props.value) {
        emit('change', blurCacheValue);
      }
      emit('blur', event);
      setEditable(false);
    };

    // 自动聚焦
    watch(editorRef, newVal => {
      if (props.autoFocus && newVal) {
        const inputTag = type.value === 'textarea' ? 'textarea' : 'input';
        const input = newVal.$el.getElementsByTagName(inputTag)[0];
        input.focus();
      }
    });
    const onFocus = (e: IData) => {
      emit('focus', e);
      setEditable(true);
    };

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let chatInstance: any;

    const onClick = async () => {
      if (c.deService) {
        const module = await import('@ibiz-template-plugin/ai-chat');
        const chat = module.chat || module.default.chat;
        chatInstance = chat;
        const aiChat = chat.create({
          question: async (arr: IChatMessage[]) => {
            const id = createUUID();
            await c.deService?.aiChatSse(
              (msg: IPortalAsyncAction) => {
                ibiz.log.info('aiChatSse', msg);
                // 20: 持续回答中，消息会持续推送。同一个消息 id 会显示在同一个框内
                if (msg.actionstate === 20 && msg.actionresult) {
                  aiChat.addMessage({
                    messageid: id,
                    state: msg.actionstate,
                    type: 'DEFAULT',
                    role: 'ASSISTANT',
                    content: msg.actionresult as string,
                  });
                }
                // 30: 回答完成，包含具体所有消息内容。直接覆盖之前的临时拼接消息
                else if (msg.actionstate === 30 && msg.actionresult) {
                  const result = JSON.parse(msg.actionresult as string);
                  const choices = result.choices;
                  if (choices && choices.length > 0) {
                    aiChat.replaceMessage({
                      messageid: id,
                      state: msg.actionstate,
                      type: 'DEFAULT',
                      role: 'ASSISTANT',
                      content: choices[0].content || '',
                    });
                  }
                }
                // 40: 回答报错，展示错误信息
                else if (msg.actionstate === 40) {
                  aiChat.replaceMessage({
                    messageid: id,
                    state: msg.actionstate,
                    type: 'ERROR',
                    role: 'ASSISTANT',
                    content: msg.actionresult as string,
                  });
                }
              },
              c.context,
              {},
              {
                messages: arr,
              },
            );
            aiChat.addMessage({
              messageid: id,
              state: 10,
              type: 'DEFAULT',
              role: 'ASSISTANT',
              content: '',
            });
            return true;
          },
          action: ((action: string, message: IChatMessage) => {
            if (action === 'backfill') {
              handleChange(message.content);
            }
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
          }) as any,
        });
        const res = await c.deService?.aiChatHistory(c.context, {});
        if (res.data && Array.isArray(res.data)) {
          res.data.forEach(item => {
            const msg = {
              messageid: createUUID(),
              state: 30,
              type: 'DEFAULT',
              role: item.role,
              content: item.content,
            } as const;
            aiChat.addMessage(msg);
          });
        }
      }
    };

    onUnmounted(() => {
      if (chatInstance) {
        chatInstance.close();
      }
    });

    // 只读文本计算和事件抛出
    const readonlyText = computed(() => {
      const { unitName } = props.controller.parent;
      // 只读显示
      let text = `${props.controller.formatValue(currentVal.value)}`;
      // 当有值且单位存在时才显示单位
      if (text && unitName) {
        text += unitName;
      }
      return text;
    });

    // 是否允许自动填充
    const shouldAutoComplete = computed(() => {
      // 根据配置的编辑器参数autocomplete来决定
      return c.model.editorParams &&
        c.model.editorParams.autocomplete &&
        c.toBoolean(c.model.editorParams.autocomplete)
        ? 'on'
        : 'new-password';
    });

    return {
      c,
      ns,
      rows,
      type,
      currentVal,
      readonlyText,
      handleChange,
      handleKeyUp,
      onBlur,
      onFocus,
      editorRef,
      onClick,
      shouldAutoComplete,
      isEditable,
      setEditable,
      showLimit,
      isAuto,
      showFormDefaultContent,
    };
  },
  render() {
    const { unitName } = this.c.parent;
    const { editorWidth, editorHeight, predefinedType } = this.c.model;

    let content = null;
    if (this.readonly) {
      // 只读显示
      content = this.readonlyText;
    } else {
      // 编辑态显示
      const slots: IData = {};
      if (unitName) {
        slots.suffix = () => {
          return <i class={this.ns.e('unit')}>{unitName}</i>;
        };
      }
      if (predefinedType === 'AUTH_USERID') {
        slots.prefix = () => <ion-icon name='person'></ion-icon>;
      } else if (predefinedType === 'AUTH_PASSWORD') {
        slots.prefix = () => <ion-icon name='unlock-alt'></ion-icon>;
      }

      content = (
        <el-input
          ref='editorRef'
          clearable={true}
          v-model={this.currentVal}
          placeholder={this.c.placeHolder}
          type={this.type}
          rows={this.rows}
          resize='none'
          autosize={this.isAuto}
          maxlength={this.c.model.maxLength}
          minlength={this.c.model.minLength}
          show-word-limit={this.showLimit && this.c.model.showMaxLength}
          onChange={this.handleChange}
          onKeyup={this.handleKeyUp}
          onBlur={this.onBlur}
          onFocus={this.onFocus}
          class={this.ns.b('input')}
          disabled={this.disabled}
          show-password={this.type === 'password'}
          autocomplete={this.shouldAutoComplete}
          {...this.$attrs}
        >
          {slots}
        </el-input>
      );
    }

    // 表单默认内容
    const formDefaultContent = (
      <div class={this.ns.b('form-default-content')}>
        {this.currentVal
          ? this.type === 'password'
            ? this.currentVal.split('').map(_item => '•')
            : this.currentVal
          : '-'}
      </div>
    );

    return (
      <div
        class={[
          this.ns.b(),
          this.ns.is('textarea', Object.is(this.type, 'textarea')),
          this.disabled ? this.ns.m('disabled') : '',
          this.readonly ? this.ns.m('readonly') : '',
          this.ns.is('editable', this.isEditable),
          this.ns.is('show-default', this.showFormDefaultContent),
        ]}
        style={{
          width: editorWidth ? `${editorWidth}px` : '',
          height: editorHeight ? `${editorHeight}px` : '',
        }}
      >
        {this.showFormDefaultContent && formDefaultContent}
        {/** autocomplete参数设置为true且类型为密码框时，添加隐藏文本框，解决浏览器不识别autocomplete参数 */}
        {this.type === 'password' &&
        this.shouldAutoComplete === 'new-password' ? (
          <input
            type={'text'}
            style='opacity: 0;position:absolute;width:0;height:0;'
          ></input>
        ) : null}

        {content}
        {this.c.chatCompletion ? (
          <div class={this.ns.e('ai-chat')} onClick={this.onClick}>
            <ion-icon src='./assets/images/svg/chat.svg' />
          </div>
        ) : null}
      </div>
    );
  },
});
